package com.linkai.JUC._03_lock8;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Description: 自旋锁
 *               主要就是 CAS 的操作，一定要有CAS
 *               2个进程都会进来加锁，但是一定要等T1解锁之后，T2才会解锁
 *               T1会自旋，T2必须等待
 *               因为T1解锁之后才会释放，T2才有机会拿到锁并解锁。
 * @Author: 林凯
 * @Date: 2021/10/26 23:14
 */
public class SpinLockDemo01 {
    public static void main(String[] args) throws InterruptedException {
        MySpinLock mySpinLock = new MySpinLock();

        new Thread(()->{
            mySpinLock.myLock();

            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                mySpinLock.myUnLock();
            }
        }, "T1").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(()->{
            mySpinLock.myLock();

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                mySpinLock.myUnLock();
            }
        }, "T2").start();

    }
}

// 自定义的自旋锁
class MySpinLock {
    // int 0
    // 使用原子引用
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    // 加锁
    public void myLock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "===>myLock");
        // 自旋锁：如果为空就加锁，一直轮询检查
        while (!atomicReference.compareAndSet(null, thread));
    }

    // 解锁
    public void myUnLock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "===>myUnLock");
        atomicReference.compareAndSet(thread, null);

    }
}
